package vsvm.data.filter.ranking;

import org.apache.commons.math.stat.descriptive.moment.Mean;
import org.apache.commons.math.stat.descriptive.moment.Variance;

public class FisherScore extends AbstractSupervisedRanking 
{
	
	private static final long serialVersionUID = 100L;

	public FisherScore(){}

	public double[] score() 
	{

		int numAttributes = dataModel.getAttributeCount();
		double[] scores = new double[numAttributes];
		generateSubsets();
		int numClasses = numberOfClasses();
		
		double[][] classMean = new double[numAttributes][numClasses];
		double[][] classVariance = new double[numAttributes][numClasses];
		
		Mean mean = new Mean();
		Variance variance = new Variance();
		
		for(int i = 0; i < numAttributes; i++)
		{		
			for(int j = 0; j < numClasses; j++)
			{
				double[] values = classFeatureValues(j, i);
				classMean[i][j] = mean.evaluate(values);
				classVariance[i][j] = variance.evaluate(values);
			}
		}
		
		double[] attributesMean = new double[numAttributes];
		
		for(int i = 0; i < numAttributes; i++)
		{
			attributesMean[i] = mean.evaluate(allFeatureValues(i));
		}
		
		double[] denominator = new double[numAttributes];
		double[] numerator = new double[numAttributes];
		double maxRatio = 0;
		
		for(int i = 0; i < numAttributes; i++)
		{
			double sum1 = 0;
			double sum2 = 0;
			
			for(int j = 0; j < numClasses; j++)
			{
				sum1 = sum1 + Math.pow(classMean[i][j] - attributesMean[i], 2) * 
																classLength(j);
				sum2 = sum2 + classLength(j) * classVariance[i][j];
			}
			denominator[i] = sum2;
			numerator[i] = sum1;
			
			if(sum2 > 1e-8)
			{
				if(sum1/sum2 > maxRatio)
				{
					maxRatio = sum1/sum2;	
				}
			}							
		}
		
		for(int i = 0; i < scores.length; i++)
		{
			if(numerator[i] > 1e-8)
			{
				if(denominator[i] < 1e-8)
				{
					scores[i] = maxRatio;				
				}
				else 
				{
					scores[i] = numerator[i]/denominator[i];	
				}
			}			
			else
			{
				scores[i] = 0;	
			}
		}	
		return scores;
	}

}
